#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by PyCharm.
# @Project: Code_Clone_Detection_Educoder
# @File: java_lexer.py
# @Description: 
# @Time: 2018/12/12 15:45
# @Author: ljz

# from CCDetector.utils import code_format

# token分类
TOKEN_STYLE = ['IDENTIFIER', 'DIGIT_CONSTANT', 'STRING_CONSTANT']
# 关键字
keywords = ['abstract', 'assert', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue',
            'default', 'do', 'double', 'else', 'enum', 'extends', 'final', 'finally', 'float', 'for', 'goto', 'if',
            'implements', 'import', 'instanceof', 'int', 'interface', 'lambda', 'long', 'main', 'native', 'new',
            'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'String', 'super',
            'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'try', 'void', 'volatile', 'while',
            'System.out.println']
# 运算符
operators = ['+', '-', '*', '/', '=', '%', '!', '>', '<', '&', '|', '^', '~', '?']
# 分隔符
delimiters = ['(', ')', '{', '}', '[', ']', ',', '\"', '\'', ':', ';']


class JavaLexer:

    def __init__(self, content):
        # 保存词法分析结果
        self.tokens = []
        self.content = content

    # 判断是否是空白字符
    def is_blank(self, index):
        return self.content[index] == ' ' or self.content[index] == '\t'

    # 跳过空白字符
    def skip_blank(self, index):
        while index < len(self.content) and self.is_blank(index):
            index += 1
        return index

    # 判断是否是关键字
    @staticmethod
    def is_keyword(value):
        if value in keywords:
            return True
        return False

    # 词法分析
    def analyze(self):
        i = 0
        while i < len(self.content):
            i = self.skip_blank(i)

            # 如果是字母或者下划线开头
            if self.content[i].isalpha() or self.content[i] == '_':
                # 获取字符串
                temp = ''
                while i < len(self.content):
                    if self.content[i].isalpha() or self.content[i] == '_' or self.content[i].isdigit():
                        temp += self.content[i]
                        i += 1
                    else:
                        break
                # 判断是否关键词
                if self.is_keyword(temp):
                    self.tokens.append(temp)
                else:
                    self.tokens.append(TOKEN_STYLE[0])
                i = self.skip_blank(i)
            # 如果是数字开头
            elif self.content[i].isdigit():
                temp = ''
                while i < len(self.content):
                    if self.content[i].isdigit() or (self.content[i] == '.' and self.content[i + 1].isdigit()):
                        temp += self.content[i]
                        i += 1
                    else:
                        break
                # 判定为数字常量
                self.tokens.append(TOKEN_STYLE[1])
                i = self.skip_blank(i)
            # 如果是分隔符
            elif self.content[i] in delimiters:
                # 如果是字符串常量
                if self.content[i] == '\"':
                    i += 1
                    temp = ''
                    escape = True
                    while i < len(self.content):
                        if self.content[i] == '\\' and self.content[i + 1] == '\\':
                            escape = not escape
                        if self.content[i] == '\\' and self.content[i + 1] != '\\' and self.content[i + 1] != '\"':
                            escape = True
                        if self.content[i] != '\"' or \
                                (self.content[i] == '\"' and self.content[i - 1] == '\\' and escape):
                            temp += self.content[i]
                            i += 1
                        else:
                            break
                    else:
                        print(' '.join(self.tokens))
                        print(temp)
                        print('error:lack of \"')
                        exit()
                    self.tokens.append(TOKEN_STYLE[2])
                elif self.content[i] == '\'':
                    i += 1
                    temp = ''
                    escape = True
                    while i < len(self.content):
                        if self.content[i] == '\\' and self.content[i + 1] == '\\':
                            escape = not escape
                        if self.content[i] == '\\' and self.content[i + 1] != '\\' and self.content[i + 1] != '\'':
                            escape = True
                        if self.content[i] != '\'' or \
                                (self.content[i] == '\'' and self.content[i - 1] == '\\' and escape):
                            temp += self.content[i]
                            i += 1
                        else:
                            break
                    else:
                        print(' '.join(self.tokens))
                        print(temp)
                        print('error:lack of \'')
                        exit()
                    self.tokens.append(TOKEN_STYLE[2])
                # 如果是其他分隔符
                else:
                    self.tokens.append(self.content[i])
                i = self.skip_blank(i + 1)
            # 如果是运算符
            elif self.content[i] in operators:
                self.tokens.append(self.content[i])
                i = self.skip_blank(i + 1)
            # 其他情况，保留原字符
            else:
                self.tokens.append(self.content[i])
                i = self.skip_blank(i + 1)

        return self.tokens


# if __name__ == '__main__':
#     with open('test.java', 'r', encoding='utf-8') as file:
#         content = file.read()
#     lexer = JavaLexer(content)
#     tokens = lexer.analyze()
#     rows = 0
#     code_information = []
#     line = []
#     for index, token in enumerate(tokens):
#         line.append(token)
#         if token == '\n' or token == '\r':
#             del line[-1]
#             rows += 1
#             code = ''.join(line)
#             code_information.append([code, rows])
#             line = []
#         elif index == len(tokens) - 1:
#             rows += 1
#             code = ''.join(line)
#             code_information.append([code, rows])
#     code_information = code_format.handle_java_annotation(code_information)
#     for i in code_information:
#         print(i)
#
#     rows = 0
#     origin_code = []
#     line_code = ''
#     for index, token in enumerate(content):
#         line_code += token
#         if token == '\n' or token == '\r':
#             rows += 1
#             origin_code.append([line_code, rows])
#             line_code = ''
#         elif index == len(content) - 1:
#             rows += 1
#             origin_code.append([line_code, rows])
#     for i in origin_code:
#         print(i)
